#define BLINKER_PRINT Serial
#define BLINKER_WIFI


#include <Blinker.h>
#include <WiFiUdp.h>
#include <WakeOnLan.h>
#include <WiFiClientSecure.h>


// WOL 唤醒
WiFiUDP UDP;
WakeOnLan WOL(UDP);
// MAC 地址
const char* MAC_ADDRESS = "00:F0:D2:D0:74:06";

// 点灯相关配置
char auth[] = "34156bb97ee9";
char ssid[] = "RedmiK30";
char pswd[] = "q1w2e3r4";

// HTTP 请求相关
const char* host = "192.168.0.22";
const int port = 8080;
const String base_url = "/computer-manager/manager/";

// wol 按钮组件
BlinkerButton Button_Wol("btn-wol");
// 关机 按钮组件
BlinkerButton Button_Shutdown("btn-shutdown");
// 重启 按钮组件
BlinkerButton Button_Restart("btn-restart");
// 撤销 按钮组件
BlinkerButton Button_Cancel("btn-cancel");
// 状态展示 按钮
BlinkerButton Button_Status("btn-status");

// 心跳包函数, 上报状态
void heartbeat() {
  btn_status_callback(BLINKER_CMD_BUTTON_TAP);
}


// wol唤醒
void btn_wol_callback(const String & state) {
  BLINKER_LOG("btn_wol enter: ", state);
  // 点击按钮, 调用 wol 方法
  if (state == BLINKER_CMD_BUTTON_TAP) {
    wakeOnLan();
    Button_Status.text("starting...");
    Button_Status.icon("fa fa-spinner");
    Button_Status.print();
  }
}

// shutdown
void btn_shutdown_callback(const String & state) {
  BLINKER_LOG("btn_shutdown enter: ", state);
  // 点击按钮, 请求 shutdown 接口
  if (state == BLINKER_CMD_BUTTON_TAP) {
    String result = post("shutdown");
    if (result == "0") {
      BLINKER_LOG("shutdown success !");
      Button_Status.text("shutting down...");
      Button_Status.icon("fa fa-spinner");
      Button_Status.print();
    } else {
      BLINKER_LOG("shutdown fail...");
    }
  }
}

// restart
void btn_restart_callback(const String & state) {
  BLINKER_LOG("btn_restart enter: ", state);
  // 点击按钮, 请求 restart 接口
  if (state == BLINKER_CMD_BUTTON_TAP) {
    String result = post("restart");
    if (result == "0") {
      BLINKER_LOG("restart success !");
    } else {
      BLINKER_LOG("restart fail...");
    }
  }
}

// cancel
void btn_cancel_callback(const String & state) {
  BLINKER_LOG("btn_cancel enter: ", state);
  // 点击按钮, 请求 cancel 接口
  if (state == BLINKER_CMD_BUTTON_TAP) {
    String result = post("cancel");
    if (result == "0") {
      BLINKER_LOG("cancel success !");
    } else {
      BLINKER_LOG("cancel fail...");
    }
    btn_status_callback(BLINKER_CMD_BUTTON_TAP);
  }
}

// status
void btn_status_callback(const String & state) {
  BLINKER_LOG("btn_status enter: ", state);
  // 点击按钮, 请求 echo 接口
  if (state == BLINKER_CMD_BUTTON_TAP) {
    String rand_str = (String) random(100);
    String result = post("echo?msg=" + rand_str);
    if (result == rand_str) {
      BLINKER_LOG("echo success !");
      Button_Status.color("#3CB371");
      Button_Status.text("online");
      Button_Status.icon("fa fa-server");
      Button_Status.print();
    } else {
      BLINKER_LOG("echo fail...");
      Button_Status.color("#A9A9A9");
      Button_Status.text("offline");
      Button_Status.icon("fa fa-server");
      Button_Status.print();
    }
  }
}

// 如果未绑定的组件被触发，则会执行其中内容
void dataRead(const String & data) {
  BLINKER_LOG("Blinker readString: ", data);
}

void setup() {
  // 初始化串口
  Serial.begin(9600);

#if defined(BLINKER_PRINT)
  BLINKER_DEBUG.stream(BLINKER_PRINT);
#endif

  // 初始化blinker
  Blinker.begin(auth, ssid, pswd);
  Blinker.attachData(dataRead);
  Button_Wol.attach(btn_wol_callback);
  Button_Shutdown.attach(btn_shutdown_callback);
  Button_Restart.attach(btn_restart_callback);
  Button_Cancel.attach(btn_cancel_callback);
  Button_Status.attach(btn_status_callback);
}

void wakeOnLan() {
  // 发送 WOL 数据包
  WOL.sendMagicPacket(MAC_ADDRESS);
  BLINKER_LOG("wakeOnLan finish...");
}

String post(String url) {
  BLINKER_LOG("http post: ", base_url + url);
  WiFiClient client;
  client.setTimeout(500);

  BLINKER_LOG("Http Connecting...");
  // 尝试连接服务器并等待
  int r = 0;
  while ((!client.connect(host, port)) && (r < 3)) {
    r ++;
    delay(100);
  }
  // 连接超时后输出"连接失败"信息并返回
  if (r == 3) {
    BLINKER_LOG("Http Connection Failed...");
    return "-1";
  } else {
    // 连接成功则输出“连接成功”信息
    BLINKER_LOG("Http Connected...");
  }

  String postRequest = (String)("POST ") + base_url + url + " HTTP/1.1\r\n" +
                       "Host: " + host + "\r\n" +
                       "Connection: close\r\n\r\n";
  client.print(postRequest);
  // 使用find跳过HTTP响应头
  if (client.find("\r\n\r\n")) {
    BLINKER_LOG("Found Header End...");
  }
  String result = client.readStringUntil('\n');
  BLINKER_LOG("Http Post Result: ", result);
  client.stop();

  return result;
}

void loop() {
  Blinker.run();
}
